﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Xml;


namespace DBSchemaService.Utils
{

    public class SchemaConfiguration : ConfigurationSection
    {
        // Create a "project" attribute.
        [ConfigurationProperty("project", IsRequired = true)]
        public string Project
        {
            get
            {
                return this["project"].ToString();
            }
            set
            {
                this["project"] = value;
            }
        }

        // Create a "database" attribute.
        [ConfigurationProperty("database", IsRequired = true)]
        public string Database
        {
            get
            {
                return this["database"].ToString();
            }
            set
            {
                this["database"] = value;
            }
        }

        // Create a "metadata" attribute.
        [ConfigurationProperty("metadata", IsRequired = true)]
        public string Metadata
        {
            get
            {
                return this["metadata"].ToString();
            }
            set
            {
                this["metadata"] = value;
            }
        }

        // Create a "tfsServerPath" attribute.
        [ConfigurationProperty("tfsServerPath", IsRequired = true)]
        public string TfsServerPath
        {
            get
            {
                return this["tfsServerPath"].ToString();
            }
            set
            {
                this["tfsServerPath"] = value;
            }
        }

        // Create a "serverPathRoot" attribute.
        [ConfigurationProperty("serverPathRoot", IsRequired = true)]
        public string ServerPathRoot
        {
            get
            {
                return this["serverPathRoot"].ToString();
            }
            set
            {
                this["serverPathRoot"] = value;
            }
        }

        // Create a "tfsServerPath" attribute.
        [ConfigurationProperty("tfsServerPath", IsRequired = true)]
        public string TFSServerPath
        {
            get
            {
                return this["tfsServerPath"].ToString();
            }
            set
            {
                this["tfsServerPath"] = value;
            }
        }

       


        // Create a "schemasRootLocalPath" attribute.
        [ConfigurationProperty("schemasRootLocalPath", IsRequired = true)]
        public string SchemasRootLocalPath
        {
            get
            {
                return this["schemasRootLocalPath"].ToString();
            }
            set
            {
                this["schemasRootLocalPath"] = value;
            }
        }

        // Create a "localPathRoot" attribute.
        [ConfigurationProperty("localPathRoot", IsRequired = true)]
        public string LocalPathRoot
        {
            get
            {
                return this["localPathRoot"].ToString();
            }
            set
            {
                this["localPathRoot"] = value;
            }
        }

        // Create a "localPath element."
        [ConfigurationProperty("localPath")]
        public LocalPathElement LocalPath
        {
            get
            {
                return (LocalPathElement)this["localPath"];
            }
            set
            { this["localPath"] = value; }
        }

        // Define the "localPath" element
        // with "value" attribute.
        public class LocalPathElement : ConfigurationElement
        {
            [ConfigurationProperty("value", IsRequired = true)]
            [StringValidator(InvalidCharacters = "~!@#$%^&*()[]{};")]
            public string Value
            {
                get
                {
                    return this["value"].ToString();
                }
                set
                {
                    this["value"] = value;
                }
            }
        }

        // Create a "connectionString" attribute.
        [ConfigurationProperty("connectionString", IsRequired = true)]
        public string ConnectionString
        {
            get
            {
                return this["connectionString"].ToString();
            }
            set
            {
                this["connectionString"] = value;
            }
        }

        // Create a "updateVersionQuery" attribute.
        [ConfigurationProperty("updateVersionQuery", IsRequired = true)]
        public string UpdateVersionQuery
        {
            get
            {
                return this["updateVersionQuery"].ToString();
            }
            set
            {
                this["updateVersionQuery"] = value;
            }
        }

        // Create a "selectVersionQuery" attribute.
        [ConfigurationProperty("selectVersionQuery", IsRequired = true)]
        public string SelectVersionQuery
        {
            get
            {
                return this["selectVersionQuery"].ToString();
            }
            set
            {
                this["selectVersionQuery"] = value;
            }
        }

        // Create a "tfsServerPathForHistoryFile" attribute.
        [ConfigurationProperty("tfsServerPathForHistoryFile", IsRequired = true)]
        public string TfsServerPathForHistoryFile
        {
            get
            {
                return this["tfsServerPathForHistoryFile"].ToString();
            }
            set
            {
                this["tfsServerPathForHistoryFile"] = value;
            }
        }

        // Create a "localPathForHistoryFile" attribute.
        [ConfigurationProperty("localPathForHistoryFile", IsRequired = true)]
        public string LocalPathForHistoryFile
        {
            get
            {
                return this["localPathForHistoryFile"].ToString();
            }
            set
            {
                this["localPathForHistoryFile"] = value;
            }
        }

        [ConfigurationProperty("createClientDBsprocFile", IsRequired = false)]
        public string CreateClientDBsprocFile
        {
            get
            {
                return this["createClientDBsprocFile"] as string;
            }
            set
            {
                this["createClientDBsprocFile"] = value;
            }
        }
        


    }


    public class StoredProcedureFileConfiguration : ConfigurationSection
    {
        // Create a "project" attribute.
        [ConfigurationProperty("project", IsRequired = true)]
        public string Project
        {
            get
            {
                return this["project"].ToString();
            }
            set
            {
                this["project"] = value;
            }
        }

        // Create a "database" attribute.
        [ConfigurationProperty("database", IsRequired = true)]
        public string Database
        {
            get
            {
                return this["database"].ToString();
            }
            set
            {
                this["database"] = value;
            }
        }

        // Create a "metadata" attribute.
        [ConfigurationProperty("metadata", IsRequired = true)]
        public string Metadata
        {
            get
            {
                return this["metadata"].ToString();
            }
            set
            {
                this["metadata"] = value;
            }
        }

        // Create a "tfsServerPath" element.
        [ConfigurationProperty("tfsServerPath")]
        public TFSServerPathElement TFSServerPath
        {
            get
            {
                return (TFSServerPathElement)this["tfsServerPath"];
            }
            set
            { this["tfsServerPath"] = value; }
        }

        // Define the "tfsServerPath" element
        // with "value" attribute.
        public class TFSServerPathElement : ConfigurationElement
        {
            [ConfigurationProperty("value", IsRequired = true)]
            [StringValidator(InvalidCharacters = "~!@#%^&*()[]{};")]
            public string Value
            {
                get
                {
                    return this["value"].ToString();
                }
                set
                {
                    this["value"] = value;
                }
            }
        }

        // Create a "localPath element."
        [ConfigurationProperty("localPath")]
        public LocalPathElement LocalPath
        {
            get
            {
                return (LocalPathElement)this["localPath"];
            }
            set
            { this["localPath"] = value; }
        }

        // Define the "localPath" element
        // with "value" attribute.
        public class LocalPathElement : ConfigurationElement
        {
            [ConfigurationProperty("value", IsRequired = true)]
            [StringValidator(InvalidCharacters = "~!@#$%^&*()[]{};")]
            public string Value
            {
                get
                {
                    return this["value"].ToString();
                }
                set
                {
                    this["value"] = value;
                }
            }
        }

        // Create a "connectionString" attribute.
        [ConfigurationProperty("connectionString", IsRequired = true)]
        public string ConnectionString
        {
            get
            {
                return this["connectionString"].ToString();
            }
            set
            {
                this["connectionString"] = value;
            }
        }

        // Create a "updateVersionQuery" attribute.
        [ConfigurationProperty("updateVersionQuery", IsRequired = true)]
        public string UpdateVersionQuery
        {
            get
            {
                return this["updateVersionQuery"].ToString();
            }
            set
            {
                this["updateVersionQuery"] = value;
            }
        }


        // Create a "sprocsRootLocalPath" attribute.
        [ConfigurationProperty("sprocsRootLocalPath", IsRequired = true)]
        public string SprocsRootLocalPath
        {
            get
            {
                return this["sprocsRootLocalPath"].ToString();
            }
            set
            {
                this["sprocsRootLocalPath"] = value;
            }
        }

        // Create a "sprocsRootServerPath" attribute.
        [ConfigurationProperty("sprocsRootServerPath", IsRequired = true)]
        public string SprocsRootServerPath
        {
            get
            {
                return this["sprocsRootServerPath"].ToString();
            }
            set
            {
                this["sprocsRootServerPath"] = value;
            }
        }
    }

    public static class ConfigurationHelper
    {
        public static List<SchemaConfiguration> GetSchemaConfigurations()
        {
            List<SchemaConfiguration> schemaInfoList = new List<SchemaConfiguration>();
            SchemaConfiguration schemaInfo = null;
            IDictionary schemaAttributes = null;
            IDictionary schemaInfoCollection = (IDictionary)ConfigurationManager.GetSection("schemas");

            foreach (object key in schemaInfoCollection.Keys)
            {
                schemaAttributes = (IDictionary)schemaInfoCollection[key];
                schemaInfo = new SchemaConfiguration();
                schemaInfo.Project = schemaAttributes["project"].ToString();
                schemaInfo.Database = schemaAttributes["database"].ToString();
                schemaInfo.Metadata = schemaAttributes["metadata"].ToString();
                schemaInfo.TFSServerPath = schemaAttributes["tfsServerPath"].ToString();
                schemaInfo.ServerPathRoot = schemaAttributes["serverPathRoot"].ToString();
                schemaInfo.SchemasRootLocalPath = schemaAttributes["schemasRootLocalPath"].ToString();
                schemaInfo.LocalPath.Value = schemaAttributes["localPath"].ToString();
                schemaInfo.LocalPathRoot = schemaAttributes["localPathRoot"].ToString();
                schemaInfo.ConnectionString = schemaAttributes["connectionString"].ToString();
                schemaInfo.UpdateVersionQuery = schemaAttributes["updateVersionQuery"].ToString();
                schemaInfo.SelectVersionQuery = schemaAttributes["selectVersionQuery"].ToString();
                schemaInfo.TfsServerPathForHistoryFile = schemaAttributes["tfsServerPathForHistoryFile"].ToString();
                schemaInfo.LocalPathForHistoryFile = schemaAttributes["localPathForHistoryFile"].ToString();
                schemaInfoList.Add(schemaInfo);
            }
            return schemaInfoList;
        }

        public static List<StoredProcedureFileConfiguration> GetStoredProcedureFileConfigurations()
        {
            List<StoredProcedureFileConfiguration> schemaInfoList = new List<StoredProcedureFileConfiguration>();
            StoredProcedureFileConfiguration schemaInfo = null;
            IDictionary schemaAttributes = null;
            IDictionary schemaInfoCollection = (IDictionary)ConfigurationManager.GetSection("sprocs");

            foreach (object key in schemaInfoCollection.Keys)
            {
                schemaAttributes = (IDictionary)schemaInfoCollection[key];
                schemaInfo = new StoredProcedureFileConfiguration();
                schemaInfo.Project = schemaAttributes["project"].ToString();
                schemaInfo.Database = schemaAttributes["database"].ToString();
                schemaInfo.Metadata = schemaAttributes["metadata"].ToString();
                schemaInfo.TFSServerPath.Value = schemaAttributes["tfsServerPath"].ToString();
                schemaInfo.LocalPath.Value = schemaAttributes["localPath"].ToString();
                schemaInfo.ConnectionString = schemaAttributes["connectionString"].ToString();
                schemaInfo.UpdateVersionQuery = schemaAttributes["updateVersionQuery"].ToString();
                schemaInfo.SprocsRootLocalPath = schemaAttributes["sprocsRootLocalPath"].ToString();
                schemaInfo.SprocsRootServerPath = schemaAttributes["sprocsRootServerPath"].ToString();
                schemaInfoList.Add(schemaInfo);
            }
            return schemaInfoList;
        }
    }

    public class ReadOnlyNameObjectDictionary : HybridDictionary, IDictionary
    {
        bool readOnly = false;
        internal void MakeReadOnly()
        {
            readOnly = true;
        }

        bool IDictionary.IsReadOnly
        {
            get
            {
                return (readOnly);
            }
        }

        object IDictionary.this[object key]
        {
            get
            {
                return (base[key]);
            }

            set
            {
                if (readOnly == false)
                {
                    base[key] = value;
                }
                else
                {
                    throw new ApplicationException("Dictionary is readonly");
                }
            }
        }
    }

    public class ElementNormalCfgHandler : IConfigurationSectionHandler
    {
        ReadOnlyNameObjectDictionary ParseSection(XmlNode section)
        {
            ReadOnlyNameObjectDictionary settingsCollection = new ReadOnlyNameObjectDictionary();

            foreach (XmlNode childNode in section.ChildNodes)
            {
                if (childNode.NodeType == XmlNodeType.Element && childNode.HasChildNodes)
                {
                    if (childNode.ChildNodes[0].NodeType == XmlNodeType.Text)
                        settingsCollection.Add(childNode.Name, childNode.InnerText);
                    else if (childNode.ChildNodes[0].NodeType == XmlNodeType.Element)
                        settingsCollection.Add(childNode.Name, ParseSection(childNode));
                }
            }

            settingsCollection.MakeReadOnly();
            return (settingsCollection);
        }

        public object Create(object parent, object configContext, XmlNode section)
        {
            return ParseSection(section);
        }
    }
}
